/*
 * Copyright (c) 2009, Michael van der Westhuizen
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    - Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above
 *      copyright notice, this list of conditions and the following
 *      disclaimer in the documentation and/or other materials provided
 *      with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef MQDESTINATION_MCVDW_20090517_H
#define MQDESTINATION_MCVDW_20090517_H

#include "imq.h"

#include "mqstatus.c"
#include "util.c"


/* *****************************************************************************
 * *****************************************************************************
 * *****************************************************************************
 * MQDestination
 * *****************************************************************************
 * *****************************************************************************
 * ****************************************************************************/


static int mqcrt_MQDestination_traverse(mqcrt_MQDestination *self, visitproc visit, void *arg)
{
    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_traverse: entry"));
    Py_VISIT(self->session);
    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_traverse: exit"));
    return 0;
}


static int mqcrt_MQDestination_clear(mqcrt_MQDestination *self)
{
    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_clear: entry"));
    Py_CLEAR(self->session);
    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_clear: exit"));
    return 0;
}


static void mqcrt_MQDestination_dealloc(mqcrt_MQDestination *self)
{
    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_dealloc: entry"));

    if (HANDLE_IS_VALID(self->destination)) {
        MQFreeDestination(self->destination);
        INIT_HANDLE(self->destination);
    }

    mqcrt_MQDestination_clear(self);
    self->ob_type->tp_free((PyObject*)self);
    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_dealloc: exit"));
}


static PyObject * mqcrt_MQDestination_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    mqcrt_MQDestination * self;
    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_new: entry"));

    if (NULL == (self = (mqcrt_MQDestination *)type->tp_alloc(type, 0))) {
        return NULL;
    }

    INIT_HANDLE(self->destination);
    self->session = NULL;
    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_new: exit"));
    return (PyObject *)self;
}


static PyObject * mqcrt_MQDestination_type(mqcrt_MQDestination *self, PyObject *args, PyObject *kwds)
{
    MQDestinationType type;

    if (setExceptionFromStatus(MQGetDestinationType(self->destination, &type))) {
        return NULL;
    }

    return Py_BuildValue("i", type);
}


static PyObject * mqcrt_MQDestination_name(mqcrt_MQDestination *self, PyObject *args, PyObject *kwds)
{
    MQString name;
    PyObject * ret;

    if (setExceptionFromStatus(MQGetDestinationName(self->destination, &name))) {
        return NULL;
    }

    ret = PyUnicode_DecodeUTF8(name, strlen(name), "strict");
    MQFreeString(name);
    return ret;
}

static PyMethodDef mqcrt_MQDestination_methods[] = {
    {"type", (PyCFunction)mqcrt_MQDestination_type, METH_NOARGS, "Get the destination type of a destination."},
    {"name", (PyCFunction)mqcrt_MQDestination_name, METH_NOARGS, "Get the destination name of a destination."},
    {NULL}
};

static PyTypeObject mqcrt_MQDestinationType = {
    PyObject_HEAD_INIT(NULL)
    0,                                       /* ob_size */
    "imq.MQDestination",                     /* tp_name */
    sizeof(mqcrt_MQDestination),             /* tp_basicsize */
    0,                                       /* tp_itemsize */
    (destructor)mqcrt_MQDestination_dealloc, /* tp_dealloc */
    0,                                       /* tp_print */
    0,                                       /* tp_getattr */
    0,                                       /* tp_setattr */
    0,                                       /* tp_compare */
    0,                                       /* tp_repr */
    0,                                       /* tp_as_number */
    0,                                       /* tp_as_sequence */
    0,                                       /* tp_as_mapping */
    0,                                       /* tp_hash */
    0,                                       /* tp_call */
    0,                                       /* tp_str */
    0,                                       /* tp_getattro */
    0,                                       /* tp_setattro */
    0,                                       /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
    "MQDestination objects",                 /* tp_doc */
    (traverseproc)mqcrt_MQDestination_traverse, /* tp_traverse */
    (inquiry)mqcrt_MQDestination_clear,      /* tp_clear */
    0,                                       /* tp_richcompare */
    0,                                       /* tp_weaklistoffset */
    0,                                       /* tp_iter */
    0,                                       /* tp_iternext */
    mqcrt_MQDestination_methods,             /* tp_methods */
    0,                                       /* tp_members */
    0,                                       /* tp_getset */
    0,                                       /* tp_base */
    0,                                       /* tp_dict */
    0,                                       /* tp_descr_get */
    0,                                       /* tp_descr_set */
    0,                                       /* tp_dictoffset */
    0,                                       /* tp_init */
    0,                                       /* tp_alloc */
    0,                                       /* tp_new */
    0,
};


static PyObject * mqcrt_MQDestination_Factory(MQDestinationHandle handle, mqcrt_MQSession * session)
{
    mqcrt_MQDestination * dst;

    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_Factory: entry"));

    if (!HANDLE_IS_VALID(handle)) {
        DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_Factory: error [invalid destination handle]"));
        PyErr_SetString(PyExc_ValueError, "destination handle is not valid");
        return NULL;
    }

    if (session && !HANDLE_IS_VALID(session->session)) {
        DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_Factory: error [invalid session handle]"));
        PyErr_SetString(PyExc_ValueError, "session handle is not valid");
        return NULL;
    }

    if (NULL == (dst = (mqcrt_MQDestination *)mqcrt_MQDestination_new(&mqcrt_MQDestinationType, NULL, NULL))) {
        DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_Factory: error [allocating new destination object]"));
        return NULL;
    }

    COPY_HANDLE(dst->destination, handle);
    dst->session = (PyObject *)session;
    Py_XINCREF(dst->session);

    DPRINTF(("%s\n", "INFO: mqcrt_MQDestination_Factory: exit"));
    return (PyObject *)dst;
}

#endif
